package com.javatest.dao;

import com.javatest.db.JdbcUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author lzy
 * @version v1.0
 * Create DateTime: 2018/7/26 16:07
 * 封装了基本的CRUD的方法，以供子类继承使用
 * 当前DAO直接在方法中获取数据库连接
 * 整体DAO采用DBUtils解决方案
 */
public class DaoBase<T> {
    private static final Logger LOGGER = LoggerFactory.getLogger(DaoBase.class);
    private QueryRunner queryRunner = new QueryRunner();
    private Class<T> clazz;

    @SuppressWarnings("unchecked")
    public DaoBase() {
        Type superClass = getClass().getGenericSuperclass();
        if (superClass instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) superClass;
            Type[] typeArgs = parameterizedType.getActualTypeArguments();
            if (typeArgs != null && typeArgs.length > 0) {
                clazz = (Class<T>) typeArgs[0];
            }
        }
    }

    /**
     * 该方法封装了INSERT\DELETE\UPDATE操作
     *
     * @param sql
     * @param args
     */
    public void update(String sql, Object... args) {
        Connection connection = null;
        try {
            connection = JdbcUtils.getConnection();
            queryRunner.update(connection, sql, args);
        } catch (Exception e) {
            LOGGER.error("[DaoBase]", e);
        } finally {
            JdbcUtils.releaseConnection(connection);
        }
    }

    /**
     * 获取T类型的实体对象
     *
     * @param sql
     * @param args
     * @return
     */
    public T get(String sql, Object... args) {
        Connection connection = null;
        try {
            connection = JdbcUtils.getConnection();
            return queryRunner.query(connection, sql, new BeanHandler<>(clazz), args);
        } catch (Exception e) {
            LOGGER.error("", e);
        } finally {
            JdbcUtils.releaseConnection(connection);
        }
        return null;
    }

    /**
     * 返回T所对应的List
     *
     * @param sql
     * @param args
     * @return
     */
    public List<T> getForList(String sql, Object... args) {
        Connection connection = null;
        try {
            connection = JdbcUtils.getConnection();
            return queryRunner.query(connection, sql, new BeanListHandler<>(clazz), args);
        } catch (Exception e) {
            LOGGER.error("", e);
        } finally {
            JdbcUtils.releaseConnection(connection);
        }
        return new ArrayList<>();
    }

    /**
     * 返回某一个字段的值，列入返回一条记录的customerName
     * 或返回数据表中有多少条记录
     *
     * @param sql
     * @param args
     * @param <E>
     * @return
     */
    public <E> E getForValue(String sql, Object... args) {
        Connection connection = null;
        try {
            connection = JdbcUtils.getConnection();
            return queryRunner.query(connection, sql, new ScalarHandler<>(), args);
        } catch (Exception e) {
            LOGGER.error("", e);
        } finally {
            JdbcUtils.releaseConnection(connection);
        }
        return null;
    }

    /**
     * 返回主键值的插入操作
     *
     * @param sql
     * @param args
     * @param <E>
     * @return
     */
    public <E> E insertReturnPk(String sql, Object... args) {
        Connection connection = null;
        try {
            connection = JdbcUtils.getConnection();
            return queryRunner.insert(connection, sql, new ScalarHandler<>(), args);
        } catch (SQLException e) {
            LOGGER.error("", e);
        } finally {
            JdbcUtils.releaseConnection(connection);
        }
        return null;
    }
}
